import {
  Body,
  Controller,
  Delete,
  Get,
  HttpException,
  HttpStatus,
  Inject,
  LoggerService,
  Logger,
  Patch,
  Post,
  Put,
  Query,
  UseFilters,
  Headers,
  UnauthorizedException,
  UseGuards,
  ParseIntPipe,
  CanActivate
} from '@nestjs/common'
import { UserService } from './user.service'
import { ConfigService } from '@nestjs/config'
// import { ConfigEnum } from 'src/enum/config.enum'
import { User } from './user.entity'
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'
import { getUserDto } from './dto/get-user.dto'
import { TypeormFilter } from '../filters/typeorm.filter'
import { AuthGuard } from '@nestjs/passport'
import { AdminGuard } from '../guards/admin.guard'
import { Roles } from '../guards/roles.decorator'
import { selfGuard } from '../guards/self.guard'
import { jwtGuard } from '../guards/jwt.guard'
// import { Logger } from 'winston'
// import { Logger } from 'nestjs-pino'

// interface T {
//   // host: string
//   // port: number
//   // username: string
//   // password: string
// }

@Controller('user')
@UseFilters(new TypeormFilter())
// 控制器守卫
@UseGuards(jwtGuard)
export class UserController {
  // userService 是一个实例变量（类属性），类型是 UserService，即 UserService 类的一个实例。
  // 相当于 this.userService = new UserService()
  // private logger = new Logger(UserController.name)
  constructor(
    protected userService: UserService,
    private configService: ConfigService,
    // private readonly logger: Logger, //从nestjs-pino中导入
    // @Inject(Logger) private readonly logger: LoggerService
    // private readonly logger: Logger
    @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService
  ) {
    this.logger.log('UserController 运行')
  }

  // 获取所有用户列表
  @Get()
  // 非常重要的知识点：
  //1. 装饰器的执行顺序，方法装饰器如果有多个，则是从下往上执行
  // @UseGuards(AdminGuard)
  // @UseGuards(AuthGuard('jwt'))
  // 2.如果使用UseGuards传递多个守卫，则从前往后执行，如果前面的没通过，则后面的Guard不会执行
  @Roles([1, 2])
  @UseGuards(AdminGuard as unknown as CanActivate)
  async getUsers(@Query() query: getUserDto): Promise<any> {
    console.log('🚀 ~ UserController ~ getUsers ~ query:', query)
    /*// this.logger.log(`请求getUsers成功`)
    // this.logger.warn(`请求getUsers成功`)
    // this.logger.error(`请求getUsers成功`)
    // const user = { isAdmin: false }
    // if (!user.isAdmin) {
    //   throw new HttpException(
    //     'User is not admin,Forbidden to access getAllUsers',
    //     HttpStatus.FORBIDDEN
    //   )
    // }
    // 1.dotenv方法
    // const db = this.configService.get<object>(ConfigEnum.db)
    // const host = this.configService.get<object>(ConfigEnum.db_HOST)
    // const url = this.configService.get<object>('db_URL')
    // const url1 = this.configService.get<object>('db1_URL')
    // console.log(db, host, url, url1)
    // console.log('hello nestjs')
    // 2.yaml方法
    // const data = this.configService.get<object>('db')
    // console.log(data)
    // 输出结果
    // console.log(process.env)
    // // 优先使用环境变量中的密码，如果没有则使用配置文件中的密码
    // console.log(this.configService.get(ConfigEnum.db_PASSWORD))
    // const password = process.env.db_PASS || this.configService.get(ConfigEnum.db_PASSWORD)
    // console.log(password)
    // return this.userService.getUsers()*/
    // 查询所有用户要做分页、排序以及按条件查询：page-页码，limit-每页页数，condition-查询条件(username,role,gender),sort-排序
    // 小问题：前端传过来的Query参数全是string类型，需要转化为number类型

    return await this.userService.findAll(query)
  }

  // 新增用户 => 管理员才可以
  @Post()
  @Roles([1])
  @UseGuards(AdminGuard as unknown as CanActivate)
  async addUsers(@Body() dto: any): Promise<any> {
    // todo 解析Body参数
    // console.log('🚀 ~ UserController ~ addUsers ~ dto:', dto)
    //返回的是一个 Promise 对象
    const user = dto as User
    return await this.userService.create(user)
    // return this.userService.addUsers()
  }
  // 作业：更新、删除

  // 更新用户信息(完整)=>只允许管理员和本人更新
  @Put()
  @Roles([1])
  @UseGuards(selfGuard)
  // 通过 @Body() 获取请求体中的 user 数据。由于使用的是 Partial<User>，所以传入的数据是部分的
  async updateUsers(
    @Query('id') id: number,
    @Body() user: Partial<User>
    // @Headers('Authorization') headers: number
  ) {
    // 请求头传递一个Authorization判断是否是一个用户在修改信息
    // todo 传递参数id
    // todo 异常处理
    // 权限1：判断用户是否是自己
    // 权限2：判断用户是否有更新user的权限=>管理员或者自己
    // 返回数据，不能包含敏感信息的password等信息
    await this.userService.update(id, user)
    return { message: `用户信息更新成功` }
    // } else {
    //   throw new UnauthorizedException('没有权限修改此用户信息')
    // }
  }

  // 修改用户密码 =>管理员和自己
  @Patch()
  async updatepws(@Query('id') id: number, @Body() password: Partial<User>) {
    const existingUser = await this.userService.findId(id)
    if (!existingUser) {
      throw new HttpException('该用户不存在', HttpStatus.NOT_FOUND)
    }
    await this.userService.updatepws(id, password)
    return { message: `用户密码更新成功` }
  }
  // 删除用户
  // @Delete(':id'): Path(路径) 参数参数过@Param获取URL路径上的参数，deleteUser(@Param('id') id: number)
  // deleteUser(@Query('id') id: number): Query(查询) 参数,id: number:表示该参数 id 是一个数字类型
  @Delete() //只有管理员可以，用户自己也不可以
  @Roles([1])
  @UseGuards(AdminGuard as unknown as CanActivate)
  async removeUser(@Query('id') id: number) {
    //todo 传递参数id
    // 判断用户是否有删除user的权限
    const existingUser = await this.userService.findId(id)
    if (!existingUser) {
      //new HttpException: 用来表示HTTP错误的基类,当api需要返回某种类型错误时抛出
      // HttpStatus:是一个枚举，包含了所有标准的HTPP状态码,HttpStatus.NOT_FOUND:表示资源没找到(404)
      throw new HttpException('该用户不存在', HttpStatus.NOT_FOUND)
    }
    console.log('delete')
    await this.userService.remove(id)
    return { message: `该用户已删除` }
  }
  // 查询用户详细信息
  @Get('/profile')

  //ParseIntPipe：用来处理参数的验证（是否为int，不是返回错误）和转换（如果传入的 id 是一个有效的字符串(比如 "123"), 会将它转换成数字 123）
  async getUserProfile(
    @Query('id', ParseIntPipe) id: number
    // d('jwt')中的validate方法返回的，PassportModule来添加的
    // @Req() req
  ): Promise<any> {
    // console.log('🚀 ~ UserController ~ getUserProfile ~ req:', req.user)
    return this.userService.findProfile(id)
  }
  // 查询用户日志
  @Get('/logs')
  async getUserLogs(): Promise<any> {
    return await this.userService.findUserLogs(2)
  }
  // 日志分组查询
  @Get('/logsByGroup')
  async getLogsByGroup(): Promise<any> {
    // return await this.userService.findLogsByGroup(2)
    const res = await this.userService.findLogsByGroup(2)
    return res.map((o) => ({
      //打印自己所需要的结果
      result: (o as { result: string; count: number }).result,
      count: (o as { result: string; count: number }).count
    }))
  }
  // 获取用户角色
  @Get('/roles')
  async getUserRoles(): Promise<any> {
    return this.userService.findUserRoles(211)
  }
}
